package utils;

import java.io.UnsupportedEncodingException;
import java.nio.ByteBuffer;
import java.nio.CharBuffer;
import java.nio.charset.Charset;

public class HexUtil {
 

	/**
	 * 用于建立十六进制字符的输出的小写字符数组
	 */
	private static final char[] DIGITS_LOWER = { '0', '1', '2', '3', '4', '5',
			'6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f' };

	/**
	 * 用于建立十六进制字符的输出的大写字符数组
	 */
	private static final char[] DIGITS_UPPER = { '0', '1', '2', '3', '4', '5',
			'6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' };

	/**
	 * 将字节数组转换为十六进制字符数组
	 * 
	 * @param data
	 *            byte[]
	 * @return 十六进制char[]
	 */
	public static char[] encodeHex(byte[] data) {
		return encodeHex(data, true);
	}

	/**
	 * 将字节数组转换为十六进制字符数组
	 * 
	 * @param data
	 *            byte[]
	 * @param toLowerCase
	 *            <code>true</code> 传换成小写格式 ， <code>false</code> 传换成大写格式
	 * @return 十六进制char[]
	 */
	public static char[] encodeHex(byte[] data, boolean toLowerCase) {
		return encodeHex(data, toLowerCase ? DIGITS_LOWER : DIGITS_UPPER);
	}

	/**
	 * 将字节数组转换为十六进制字符数组
	 * 
	 * @param data
	 *            byte[]
	 * @param toDigits
	 *            用于控制输出的char[]
	 * @return 十六进制char[]
	 */
	protected static char[] encodeHex(byte[] data, char[] toDigits) {
		int l = data.length;
		char[] out = new char[l << 1];
		// two characters form the hex value.
		for (int i = 0, j = 0; i < l; i++) {
			out[j++] = toDigits[(0xF0 & data[i]) >>> 4];
			out[j++] = toDigits[0x0F & data[i]];
		}
		return out;
	}

	/**
	 * 将字节数组转换为十六进制字符串
	 * 
	 * @param data
	 *            byte[]
	 * @return 十六进制String
	 */
	public static String encodeHexStr(byte[] data) {
		return encodeHexStr(data, true);
	}

	/**
	 * 将字节数组转换为十六进制字符串
	 * 
	 * @param data
	 *            byte[]
	 * @param toLowerCase
	 *            <code>true</code> 传换成小写格式 ， <code>false</code> 传换成大写格式
	 * @return 十六进制String
	 */
	public static String encodeHexStr(byte[] data, boolean toLowerCase) {
		return encodeHexStr(data, toLowerCase ? DIGITS_LOWER : DIGITS_UPPER);
	}

	/**
	 * 将字节数组转换为十六进制字符串
	 * 
	 * @param data
	 *            byte[]
	 * @param toDigits
	 *            用于控制输出的char[]
	 * @return 十六进制String
	 */
	protected static String encodeHexStr(byte[] data, char[] toDigits) {
		return new String(encodeHex(data, toDigits));
	}

	/**
	 * 将十六进制字符数组转换为字节数组
	 * 
	 * @param data
	 *            十六进制char[]
	 * @return byte[]
	 * @throws RuntimeException
	 *             如果源十六进制字符数组是一个奇怪的长度，将抛出运行时异常
	 */
	public static byte[] decodeHex(char[] data) {

		int len = data.length;

		if ((len & 0x01) != 0) {
			throw new RuntimeException("Odd number of characters.");
		}

		byte[] out = new byte[len >> 1];

		// two characters form the hex value.
		for (int i = 0, j = 0; j < len; i++) {
			int f = toDigit(data[j], j) << 4;
			j++;
			f = f | toDigit(data[j], j);
			j++;
			out[i] = (byte) (f & 0xFF);
		}

		return out;
	}

	// char转byte
	private byte[] getBytes(char[] chars) {
		Charset cs = Charset.forName("UTF-8");
		CharBuffer cb = CharBuffer.allocate(chars.length);
		cb.put(chars);
		cb.flip();
		ByteBuffer bb = cs.encode(cb);

		return bb.array();
	}

	// byte转char
	private char[] getChars(byte[] bytes) {
		Charset cs = Charset.forName("UTF-8");
		ByteBuffer bb = ByteBuffer.allocate(bytes.length);
		bb.put(bytes);
		bb.flip();
		CharBuffer cb = cs.decode(bb);

		return cb.array();
	}

	/**
	 * 将Hex字符串转换成ASCI字符串
	 * 
	 * @param strHex
	 * @return
	 * @throws Exception
	 */
	public static String HexToAsciSting(String strHex) throws Exception {
		byte[] bytes = StringToBytes(strHex);
		String strAsci = new String(bytes, "GBK");
		return strAsci;
	}

	// public static String HexToAsciiString(String strHex){
	// byte [] bytes = StringToBytes(strHex);
	// String strAsci = "";
	// try {
	// strAsci = new String(bytes,"GBK");
	// } catch (UnsupportedEncodingException e) {
	// strAsci = "";
	// }
	// return strAsci;
	// }
	public static String HexToAsciiString(String strHex) {
		byte[] bytes = StringToBytes(strHex);
		int i = 0;
		for (i = 0; i < bytes.length; i++) {
			if (bytes[i] == 0)
				break;
		}
		String strAsci = "";
		try {
			strAsci = new String(bytes, 0, i, "GBK");
		} catch (UnsupportedEncodingException e) {
			strAsci = "";
		}
		return strAsci;
	}

	/**
	 * 将一个ASCI字符串转成HEX字符串
	 * 
	 * @param strAsci
	 * @return
	 * @throws UnsupportedEncodingException
	 */
	public static String AsciToHexString(String strAsci)
			throws UnsupportedEncodingException {
		String s = String.valueOf(strAsci);
		byte[] bytes = s.getBytes("GBK");// e4baac413132333435000000
		// for (int i = 0; i < bytes.length; i++)
		// strHex += Integer.toHexString(bytes[i] & 0xff);
		// strHex.toLowerCase();
		return HexToString(bytes);
	}

	/**
	 * 将一个ASCI字符串转成HEX字符串,限定长度
	 * 
	 * @param strAsci
	 * @param nLen长度限定
	 *            ,不足的补字符0
	 * @return
	 * @throws UnsupportedEncodingException
	 */
	public static String AsciToHexString(String strAsci, int nLen)
			throws UnsupportedEncodingException {
		String s = String.valueOf(strAsci);
		byte[] bytes = s.getBytes("GBK");// e4baac413132333435000000
		String strResult = HexToString(bytes);
		int strLen = strResult.length();
		if (strLen >= nLen)
			strResult = strResult.substring(0, nLen);
		else {
			int nAddLen = nLen - strLen;
			for (int i = 0; i < nAddLen; i++)
				strResult += "0";
		}

		return strResult;
	}

	public static String HexToString(byte[] inHex) {
		int i;
		StringBuilder strResult = new StringBuilder();
		strResult.append("");
		for (i = 0; i < inHex.length; i++) {
			strResult.append(String
					.valueOf(DIGITS_UPPER[(0xF0 & inHex[i]) >>> 4]));
			strResult.append(String.valueOf(DIGITS_UPPER[inHex[i] & 0x0F]));
		}
		return strResult.toString();
	}

	public static String BytesToString(byte[] inHex, int nOff, int nLen) {
		int i;
		StringBuilder strResult = new StringBuilder();
		strResult.append("");
		for (i = 0; i < nLen; i++) {
			strResult.append(String
					.valueOf(DIGITS_UPPER[(0xF0 & inHex[nOff + i]) >>> 4]));
			strResult.append(String
					.valueOf(DIGITS_UPPER[inHex[nOff + i] & 0x0F]));
		}
		return strResult.toString();
	}

	// 十进制转化为十六进制，结果为C8。
	// Integer.toHexString(200);
	/**
	 * 1字节转成2个字符串十六进制字符串
	 * 
	 * @param dec
	 * @return
	 */
	public static String ByteToString(byte dec) {
		return String.valueOf(DIGITS_UPPER[(0xF0 & dec) >>> 4])
				+ String.valueOf(DIGITS_UPPER[dec & 0x0F]);
	}

	public static String ByteToString(int dec) {
		return String.valueOf(DIGITS_UPPER[(0xF0 & dec) >>> 4])
				+ String.valueOf(DIGITS_UPPER[dec & 0x0F]);
	}

	// 十六进制转化为十进制，结果140。
	// Integer.parseInt("8C",16);
	/**
	 * 2个字符十六进制字符串转成byte
	 * 
	 * @param str
	 * @return
	 */
	public static byte StringToByte(String str) {
		return (byte) Integer.parseInt(str, 16);
	}

	public static byte[] LongToHex(long inLong, int nLen, int flagOb) {
		int i = 0;
		byte[] outHex = new byte[nLen];
		for (i = 0; i < nLen; i++) {
			if (flagOb != 0)
				outHex[nLen - 1 - i] = (byte) (inLong >> (8 * (nLen - 1 - i)));
			else
				outHex[i] = (byte) (inLong >> (8 * (nLen - 1 - i)));
		}
		return outHex;

	}

	/**
	 * 整数转成十六进制格式字符串
	 */
	public static String LongToHexString(long inLong, int nLen, int flagOb) {
		return HexToString(LongToHex(inLong, nLen, flagOb));
	}

	/**
	 * 十六进制格式字符串转成整数
	 * 
	 * @param hexstr
	 *            最多8个字符
	 * @return
	 */
	public static long HexStringToLong(String hexstr) {
		int nlen = hexstr.length() / 2;
		long lResult = 0;
		long lTmp;
		byte byteTmp;
		for (int i = 0; i < nlen; i++) {
			byteTmp = StringToByte(hexstr.substring(i * 2, (i + 1) * 2));
			lTmp = (byteTmp & 0xFF) << (nlen - i - 1) * 8;
			lResult += lTmp;
		}
		return lResult;
	}

	/**
	 * 整形字符串转成十六进制字符串
	 * 
	 * @param str
	 * @param nLimitLen
	 *            转换后字符的长度,必须是2的整数倍
	 * @return
	 */
	public static String IntStringToHexString(String str, int nLimitLen) {
		int nValue = Integer.parseInt(str);
		int nLen = nLimitLen / 2;
		byte[] hexs = LongToHex(nValue, nLen, 0);
		String strResult = HexToString(hexs);
		return strResult;
	}

	/**
	 * 将字符串转成byte[]
	 * 
	 * @param str
	 * @return
	 */
	public static byte[] StringToBytes(String str) {
		int nLen = str.length();
		byte bytes[] = new byte[str.length() / 2];
		for (int i = 0; i < nLen / 2; i++) {
			bytes[i] = StringToByte(str.substring(i * 2, i * 2 + 2));
		}
		return bytes;
	}

	/**
	 * 将字符串补80后转成byte[]
	 * 
	 * @param str
	 * @return
	 */
	public static byte[] StringToBytes80(String str, int flagMac) {
		String str80 = str;
		int nLen = str.length();
		int add80Len = 8;

		if ((nLen / 2 % 8) != 0)
			add80Len = 8 - (nLen / 2 % 8);
		if (flagMac == 0) {
			if ((add80Len == 8))
				add80Len = 0;
		}

		for (int i = 0; i < add80Len; i++) {
			if (i == 0)
				str80 += "80";
			else
				str80 += "00";
		}
		nLen = str80.length() / 2;
		byte bytes[] = new byte[nLen];
		for (int i = 0; i < nLen; i++) {
			bytes[i] = StringToByte(str80.substring(i * 2, i * 2 + 2));
		}
		return bytes;
	}

	public static String StringApp80(String str, int flagMac) {
		String str80 = str;
		int nLen = str.length();
		int add80Len = 8;
		if ((nLen / 2 % 8) != 0)
			add80Len = 8 - (nLen / 2 % 8);
		if (flagMac == 0) {
			if ((add80Len == 8))
				add80Len = 0;
		}
		for (int i = 0; i < add80Len; i++) {
			if (i == 0)
				str80 += "80";
			else
				str80 += "00";
		}
		return str80;
	}

	/**
	 * 计算3DESMAC
	 * 
	 * @param Rand
	 * @param Key
	 * @param Value
	 * @return
	 */
//	public static String CalDesMac(String Rand, String Key, String Value) {
//		String strMac = new String();
//		strMac = "";
//		byte[] byteRand;
//		byteRand = StringToBytes(Rand.substring(0, 16));
//		byte[] byteKey;
//		byteKey = StringToBytes(Key.substring(0, 32));
//		byte[] byteValue;
//		byteValue = StringToBytes80(Value, 1);
//		byte[] bytesResult;
//		bytesResult = desmac.CalDesMac(byteRand, byteKey, byteValue);
//		strMac = HexToString(bytesResult);
//		return strMac;
//	}

	/**
	 * IDEA加密数据
	 * 
	 * @param Key
	 * @param Value
	 * @return
	 */


	/**
	 * DES解密
	 * 
	 * @param Key
	 * @param Value
	 * @return
	 */
//	public static String jiemi(String mingwen) {
//		String key = "00000000000000000000000000000000";
//		String strResult = new String();
//		strResult = "";
//		byte[] byteKey;
//		byteKey = StringToBytes(key.substring(0, 32));
//		byte[] byteValue;
//		byteValue = StringToBytes80(mingwen, 0);
//		byte[] bytesResult;
//		byte[] de3Des = desmac.De3Des(byteKey, byteValue);
//		strResult = HexToString(de3Des);
//		return strResult;
//
//	}

	/**
	 * DES加密
	 * 
	 * @param Key
	 * @param Value
	 * @return
	 */
//	public static String Encoding3Des(String Key, String Value) {
//		String strResult = new String();
//		strResult = "";
//		byte[] byteKey;
//		byteKey = StringToBytes(Key.substring(0, 32));
//		byte[] byteValue;
//		byteValue = StringToBytes80(Value, 0);
//		byte[] bytesResult;
//		bytesResult = desmac.En3Des(byteKey, byteValue);
//		strResult = HexToString(bytesResult);
//		return strResult;
//	}

	/**
	 * 生成指纹码
	 * 
	 * @param Rand
	 * @param SessionKey
	 * @param Value
	 * @return
	 */
//	public static String CalFingerprintKey(String Rand, String SessionKey,
//			String Value) {
//		Log.i("test", Value);
//		// String Result = HexUtil.EncodingIdea(SessionKey, Value);
//		String Result = HexUtil.Encoding3Des(SessionKey, Value);
//		Log.i("计算IDEA:", Result);
//		String macResult = HexUtil.CalDesMac(Rand, SessionKey.substring(8, 40),
//				Result);
//		Log.i("计算MAC:", macResult);
//		return macResult;
//	}

//	public static String CalCrc(String Value) {
//		char usIniCrc = 0x5075;
//		char usResult;
//
//		byte[] byteValue;
//		byteValue = StringToBytes(Value);
//
//		usResult = desmac.GetCrc(usIniCrc, byteValue);
//		String strResult = HexToString(LongToHex(usResult, 2, 0));
//		return strResult;
//	}

	/**
	 * 产生字节随机数
	 * 
	 * @param numByte
	 *            字节个数
	 * @return
	 */
	public static String GetRand(int numByte) {
		// (int)(Math.Random()*n)
		String strRandom = new String();
		strRandom = "";
		for (byte i = 0; i < numByte; i++)
			strRandom += ByteToString((byte) ((int) (Math.random() * 255)));
		return strRandom;
	}

	/**
	 * 将十六进制字符转换成一个整数
	 * 
	 * @param ch
	 *            十六进制char
	 * @param index
	 *            十六进制字符在字符数组中的位置
	 * @return 一个整数
	 * @throws RuntimeException
	 *             当ch不是一个合法的十六进制字符时，抛出运行时异常
	 */
	protected static int toDigit(char ch, int index) {
		int digit = Character.digit(ch, 16);
		if (digit == -1) {
			throw new RuntimeException("Illegal hexadecimal character " + ch
					+ " at index " + index);
		}
		return digit;
	}

	void f_buff_xor(byte[] buf1, byte[] buf2, int i_len) {
		int i;
		for (i = 0; i < i_len; i++) {
			buf1[i] = (byte) (buf1[i] ^ buf2[i]);
		}
	}

	public static void main(String[] args) {
		String srcStr = "待转换字符串";
		String encodeStr = encodeHexStr(srcStr.getBytes());
		String decodeStr = new String(decodeHex(encodeStr.toCharArray()));
		System.out.println("转换前：" + srcStr);
		System.out.println("转换后：" + encodeStr);
		System.out.println("还原后：" + decodeStr);
	}

	public String strHello;

	public String hello(String str) {
		String strTmp = new String();
		strTmp = strHello + str;
		return strTmp;
	}

	public void hello2(String str) {
		strHello = str;
	}

	/**
	 * 计算bcd值
	 * 
	 * @param asc
	 * @return
	 */
	public static byte[] str2Bcd(String asc) {
		int len = asc.length();
		int mod = len % 2;
		if (mod != 0) {
			asc = "0" + asc;
			len = asc.length();
		}
		byte abt[] = new byte[len];
		if (len >= 2) {
			len = len / 2;
		}
		byte bbt[] = new byte[len];
		abt = asc.getBytes();
		int j, k;
		for (int p = 0; p < asc.length() / 2; p++) {
			if ((abt[2 * p] >= '0') && (abt[2 * p] <= '9')) {
				j = abt[2 * p] - '0';
			} else if ((abt[2 * p] >= 'a') && (abt[2 * p] <= 'z')) {
				j = abt[2 * p] - 'a' + 0x0a;
			} else {
				j = abt[2 * p] - 'A' + 0x0a;
			}
			if ((abt[2 * p + 1] >= '0') && (abt[2 * p + 1] <= '9')) {
				k = abt[2 * p + 1] - '0';
			} else if ((abt[2 * p + 1] >= 'a') && (abt[2 * p + 1] <= 'z')) {
				k = abt[2 * p + 1] - 'a' + 0x0a;
			} else {
				k = abt[2 * p + 1] - 'A' + 0x0a;
			}
			int a = (j << 4) + k;
			byte b = (byte) a;
			bbt[p] = b;
		}
		return bbt;
	}
}
